package com.haole.ecommercepay.media;

import com.alibaba.fastjson.JSONObject;
import com.haole.ecommercepay.common.BaseParam;
import com.haole.ecommercepay.common.CertificateUtils;
import com.haole.ecommercepay.common.SignUtils;
import com.haole.ecommercepay.common.UuidUtils;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;

/**
 * @author haole
 */
public class Upload {

    /**
     * 上传图片
     * @param httpImage
     * @return
     */
    public static JSONObject image(String httpImage) {
        BaseParam baseParam = new BaseParam();
        JSONObject result = new JSONObject();
        try {

            // 换行符
            String LINE_END ="\r\n";
            String PREFIX ="--";
            // 定义数据分隔线
            String BOUNDARY = "----------" + System.currentTimeMillis();

            //商户私钥
            String mchPrivateKey = CertificateUtils.getPrivateKey(baseParam.getMchPrivateKeyPath());

            //时间戳
            String timestamp = Long.toString(System.currentTimeMillis()/1000);
            //随机数
            String nonce_str = UuidUtils.randomUUID();

            //图片文件
            File file = getFile(httpImage);
            String fileName = file.getName();//文件名
            String fileSha256 = DigestUtils.sha256Hex(new FileInputStream(file));//文件sha256值


            //拼签名串
            StringBuilder sb = new StringBuilder();
            sb.append("POST").append("\n");
            sb.append("/v3/merchant/media/upload").append("\n");
            sb.append(timestamp).append("\n");
            sb.append(nonce_str).append("\n");
            sb.append("{\"filename\":\"").append(fileName).append("\",\"sha256\":\"").append(fileSha256).append("\"}").append("\n");
            System.out.println("签名原串:"+sb.toString());

            //计算签名
            String sign = new String(Base64.encodeBase64(SignUtils.v3signRSA(sb.toString(),mchPrivateKey)));
            System.out.println("签名sign值:"+sign);

            //拼装http头的Authorization内容
            String authorization ="WECHATPAY2-SHA256-RSA2048 mchid=\""+baseParam.getMchId()+"\",nonce_str=\""+nonce_str+"\",signature=\""+sign+"\",timestamp=\""+timestamp+"\",serial_no=\""+baseParam.getMchSerialNo()+"\"";
            System.out.println("authorization值:"+authorization);

            //接口URL
            URL url = new URL("https://api.mch.weixin.qq.com/v3/merchant/media/upload");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            // 设置为POST
            conn.setRequestMethod("POST");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 设置请求头参数
            conn.setRequestProperty("Charsert","UTF-8");
            conn.setRequestProperty("Accept","application/json");
            conn.setRequestProperty("Content-Type","multipart/form-data; boundary=" + BOUNDARY);
            conn.setRequestProperty("Authorization", authorization);

            DataOutputStream dos = new DataOutputStream(conn.getOutputStream());

            //拼装请求内容第一部分
            StringBuilder strSb = new StringBuilder();
            strSb.append(PREFIX).append(BOUNDARY).append(LINE_END)
                    .append("Content-Disposition: form-data; name=\"meta\";" + LINE_END)
                    .append("Content-Type: application/json; " + LINE_END)
                    .append(LINE_END)// 空行
                    .append("{\"filename\":\""+fileName+"\",\"sha256\":\""+fileSha256+"\"}")
                    .append(LINE_END);
            dos.write(strSb.toString().getBytes());

            dos.flush();

            //拼装请求内容第二部分
            StringBuilder fileSbStart =new StringBuilder();
            fileSbStart.append(PREFIX).append(BOUNDARY).append(LINE_END)
                    .append("Content-Disposition: form-data; name=\"file\"; filename=\""+ fileName+"\";" + LINE_END)
                    .append("Content-Type: image/jpeg" + LINE_END)
                    .append(LINE_END);// 空行
            dos.write(fileSbStart.toString().getBytes());

            dos.flush();

            //文件二进制内容
            InputStream is = new FileInputStream(file);
            byte[] buffer = new byte[1024];
            int len =0;
            while ((len = is.read(buffer)) != -1){
                dos.write(buffer,0,len);
            }
            is.close();

            //拼装请求内容结尾
            StringBuilder fileSbEnd =new StringBuilder();
            fileSbEnd.append(LINE_END)
                    .append(PREFIX).append(BOUNDARY).append(PREFIX)
                    .append(LINE_END);

            dos.write(fileSbEnd.toString().getBytes());

            dos.flush();
            dos.close();

            //接收返回
            //打印返回头信息
            System.out.println("接口返回头信息:");
            Map<String, List<String>> responseHeader = conn.getHeaderFields();
            for (Map.Entry<String, List<String>> entry : responseHeader.entrySet()) {
                System.out.println(entry.getKey()+":" + entry.getValue());
            }

            //打印返回内容
            int responseCode = conn.getResponseCode();
            System.out.println("responseCode:"+responseCode);
            String rescontent = new String(InputStreamTOByte(conn.getInputStream()));

            result =  JSONObject.parseObject(rescontent);

            //验证微信支付返回签名
            String Wtimestamp = responseHeader.get("Wechatpay-Timestamp").get(0);
            String Wnonce = responseHeader.get("Wechatpay-Nonce").get(0);
            String Wsign = responseHeader.get("Wechatpay-Signature").get(0);
            //拼装待签名串
            StringBuffer ss =new StringBuffer();
            ss.append(Wtimestamp).append("\n");
            ss.append(Wnonce).append("\n");
            ss.append(rescontent).append("\n");
            //验证签名
            if(SignUtils.v3VerifyRSA(ss.toString(), Base64.decodeBase64(Wsign.getBytes()), baseParam.getWechatPubKeyPath())) {
                result.put("requestStatus",responseCode);
                result.put("Request-ID",responseHeader.get("Request-ID").get(0));
                System.out.println("Request-ID："+responseHeader.get("Request-ID").get(0));
            }else {
                result.put("requestStatus",1001);
                result.put("message","验签失败");
            }
        } catch (Exception e) {
            System.out.println("发送POST请求异常！" + e);
            e.printStackTrace();
        }
        return result;
    }

    public static byte[] InputStreamTOByte(InputStream in)throws IOException {

        int BUFFER_SIZE = 4096;
        ByteArrayOutputStream outStream =new ByteArrayOutputStream();
        byte[] data =new byte[BUFFER_SIZE];
        int count = -1;

        while((count = in.read(data,0,BUFFER_SIZE)) != -1)
            outStream.write(data,0, count);

        data =null;
        byte[] outByte = outStream.toByteArray();
        outStream.close();

        return outByte;
    }

    /**
     * 下载图片到本地
     *
     * @param netUrl
     * @param savePath
     * @throws Exception
     */
    public static String download(String netUrl, String savePath) throws Exception {
        String fileName = netUrl.substring(netUrl.lastIndexOf("/") + 1);
        // 构造URL
        URL url = new URL(netUrl);
        // 打开连接
        URLConnection con = url.openConnection();
        //设置请求超时为5s
        con.setConnectTimeout(5 * 1000);
        // 输入流
        InputStream is = con.getInputStream();
        // 1K的数据缓冲
        byte[] bs = new byte[1024];
        // 读取到的数据长度
        int len;
        // 输出的文件流
        File sf = new File(savePath);
        if (!sf.exists()) {
            sf.mkdirs();
        }
        OutputStream os = new FileOutputStream(sf.getPath() + "/" + fileName);
        // 开始读取
        while ((len = is.read(bs)) != -1) {
            os.write(bs, 0, len);
        }
        // 完毕，关闭所有链接
        os.close();
        is.close();
        return savePath + fileName;
    }

    public static void deleteFile(String filePath) {
        File localFile = new File(filePath);
        if (localFile.exists()){
            localFile.delete();
        }
    }

    private static File getFile(String url) throws Exception {
        //对本地文件命名
        String fileName = url.substring(url.lastIndexOf("."),url.length());
        File file = null;

        URL urlfile;
        InputStream inStream = null;
        OutputStream os = null;
        try {
            file = File.createTempFile("net_url", fileName);
            //下载
            urlfile = new URL(url);
            inStream = urlfile.openStream();
            os = new FileOutputStream(file);

            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = inStream.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != os) {
                    os.close();
                }
                if (null != inStream) {
                    inStream.close();
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return file;
    }
}
